package com.ciei.dpagm.interceptor;

import com.alibaba.fastjson.JSONObject;
import com.ciei.dpagm.common.enums.AccessEntranceEnum;
import com.ciei.dpagm.common.enums.ErrorCodeEnum;
import com.ciei.dpagm.entity.Users;
import com.ciei.dpagm.service.LoginService;
import com.ciei.dpagm.util.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author laj
 *
 */
@Component
public class RequestInterceptor implements HandlerInterceptor {

	private static final Logger logger = LoggerFactory.getLogger(RequestInterceptor.class);

	private final String USER_ID = "userId";

	private final String USER_NAME = "userName";

	private final String ACCESS_ENTRANCE_TOKEN= "accessEntranceToken";

	@Autowired
	private LoginService loginService;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		String path = request.getServletPath();
		String token = request.getHeader("authorization");
		logger.info("[p] method:{} path: {} cookie:{} authorization:{}", new Object[] { request.getMethod(), path, request.getCookies() == null ? "" : request.getCookies()[0].getValue(),token});
		if (StringUtils.isNotBlank(token) && !path.equals("/error")){
			JwtVerifyResult jwtVerifyResult = JwtUtils.validateToken(token);
			if (jwtVerifyResult.getSuccess()){
				String userId = jwtVerifyResult.getPayload().get(USER_ID);
				String accessEntranceToken = jwtVerifyResult.getPayload().get(ACCESS_ENTRANCE_TOKEN);
				if (StringUtils.isNoneBlank(userId,accessEntranceToken)){
					AccessEntranceEnum accessEntranceEnum = AccessEntranceEnum.entranceValueOf(accessEntranceToken);
					if (accessEntranceEnum != null){
						Users user = (Users) SecurityUtils.getSubject().getPrincipal();
						if (user == null){
							loginService.login(userId,jwtVerifyResult.getPayload().get(USER_NAME),accessEntranceEnum.getDescription());
						}
						return true;
					}else {
						response.setContentType("application/json;charset=utf-8");
						JSONObject json = JsonUtil.getFail(ErrorCodeEnum.NO_AUTHORIZATION,"参数accessEntranceToken无效!");
						response.getWriter().write(json.toJSONString());
						return false;
					}
				}else{
					response.setContentType("application/json;charset=utf-8");
					JSONObject json = JsonUtil.getFail(ErrorCodeEnum.NO_AUTHORIZATION,"签名缺少必须参数!");
					response.getWriter().write(json.toJSONString());
					return false;
				}
			}else {
				response.setContentType("application/json;charset=utf-8");
				JSONObject json = JsonUtil.getFail(ErrorCodeEnum.NO_AUTHORIZATION,"签名无效!");
				response.getWriter().write(json.toJSONString());
				return false;
			}
		}
		if (!path.startsWith("/resources/")) {
			// 页面访问控制，只有已登录用户才能访问系统，但登录与注册模块无需登录
			// 登录页"/"、登录"/login/check"、退出"/logout"、注册页"/register/page"、注册"/register"
			if (!(path.equals("/") || path.equals("/login") || path.equals("/login/check") || path.equals("/logout") || path.startsWith("/register") || path.equals("/error"))) {
				Users user = (Users) SecurityUtils.getSubject().getPrincipal();
				if (user == null) {
					response.setContentType("application/json;charset=utf-8");
					JSONObject json = JsonUtil.getFail(ErrorCodeEnum.NO_AUTHORIZATION.getDescription())
							.fluentPut(APP.ERROR_CODE, ErrorCodeEnum.NO_AUTHORIZATION.getErrorCode());
					response.getWriter().write(json.toJSONString());
					return false;
				}
			}
		}
		return true;
	}
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView){
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex){
	}

}
